package ioc

import (
	"fmt"
	"path/filepath"
	"strings"

	"gitee.com/hexug/go-tools/logger"
	"github.com/emicklei/go-restful/v3"
	"github.com/gin-gonic/gin"
	"google.golang.org/grpc"
)

var (
	Container = NewIocContainter()
)

type IocContainter struct {
	appObjs        map[string]AppManager
	restfulApiObjs map[string]RestfulApiManager
	ginApiObjs     map[string]GinApiManager
	grpcObjs       map[string]GrpcManager
	confObjs       map[string]ConfManager
	*LoadConfigRequest
}

func NewIocContainter() *IocContainter {
	return &IocContainter{
		appObjs:           make(map[string]AppManager),
		restfulApiObjs:    make(map[string]RestfulApiManager),
		ginApiObjs:        make(map[string]GinApiManager),
		grpcObjs:          make(map[string]GrpcManager),
		confObjs:          make(map[string]ConfManager),
		LoadConfigRequest: NewLoadConfigRequest(),
	}
}

// ------------------------------------APP-----------------------------------------------------

func (i *IocContainter) RegisterApp(obj AppManager) {
	if _, ok := i.appObjs[obj.Name()]; ok {
		logger.L().Errorw("App 注册失败",
			"name", obj.Name(),
			"reason", "已经注册过了，无法重复注册",
		)
	} else {
		i.appObjs[obj.Name()] = obj
		//logger.L().Infow("App 注册成功",
		//	"name", obj.Name(),
		//)
	}
}

func (i *IocContainter) GetApp(name string) AppManager {
	if obj, ok := i.appObjs[name]; ok {
		return obj
	}
	logger.L().PanicWithIconw("App 未注册",
		"name", name,
		"error", fmt.Errorf("App %s 未注册，故无法获取", name),
	)
	return nil
}

func (i *IocContainter) InitApps() {
	for _, obj := range i.appObjs {
		if err := obj.Init(); err != nil {
			logger.L().PanicWithIconw("App 初始化失败",
				"name", obj.Name(),
				"error", err,
			)
		}
	}
}

// ------------------------------------RestfulAPI-----------------------------------------------------

func (i *IocContainter) RegisterRestfulAPI(obj RestfulApiManager) {
	if _, ok := i.restfulApiObjs[obj.Name()]; ok {
		logger.L().Errorw("API 注册失败",
			"name", obj.Name(),
			"reason", "已经注册过了，无法重复注册",
		)
	} else {
		i.restfulApiObjs[obj.Name()] = obj
		//logger.L().Infow("API 注册成功",
		//	"name", obj.Name(),
		//)
	}
}

func (i *IocContainter) GetRestfulAPI(name string) RestfulApiManager {
	if obj, ok := i.restfulApiObjs[name]; ok {
		return obj
	}
	logger.L().PanicWithIconw("API 未注册",
		"name", name,
		"error", fmt.Errorf("API %s 未注册，故无法获取", name),
	)
	return nil
}

func (i *IocContainter) InitRestfulAPIs(pathPrefix string, r *restful.Container) {
	pathPrefix = strings.Trim(pathPrefix, "/")
	for _, obj := range i.restfulApiObjs {
		if err := obj.Init(); err != nil {
			logger.L().PanicWithIconw("API 初始化失败",
				"name", obj.Name(),
				"error", err,
			)
		}
		ws := new(restful.WebService)
		ws.Path(fmt.Sprintf("/%s/%s/%s", pathPrefix, obj.Version(), obj.Name())).
			// 设置可以用来解析的格式
			Consumes(restful.MIME_JSON, restful.MIME_XML).
			// 设置返回数据的格式
			Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well
		obj.RegisterRouter(ws)
		r.Add(ws)
	}
}

// ------------------------------------GinAPI-----------------------------------------------------

func (i *IocContainter) RegisterGinAPI(obj GinApiManager) {
	if _, ok := i.ginApiObjs[obj.Name()]; ok {
		logger.L().Errorw("API 注册失败",
			"name", obj.Name(),
			"reason", "已经注册过了，无法重复注册",
		)
	} else {
		i.ginApiObjs[obj.Name()] = obj
		//logger.L().Infow("API 注册成功",
		//	"name", obj.Name(),
		//)
	}
}

func (i *IocContainter) GetGinAPI(name string) GinApiManager {
	if obj, ok := i.ginApiObjs[name]; ok {
		return obj
	}
	logger.L().PanicWithIconw("API 未注册",
		"name", name,
		"error", fmt.Errorf("API %s 未注册，故无法获取", name),
	)
	return nil
}

func (i *IocContainter) InitGinAPIs(router gin.IRouter) {
	for _, obj := range i.ginApiObjs {
		if err := obj.Init(); err != nil {
			logger.L().PanicWithIconw("API 初始化失败",
				"name", obj.Name(),
				"error", err,
			)
		}
		obj.RegisterRouter(router)
	}
}

// ------------------------------------GRPC-----------------------------------------------------

func (i *IocContainter) RegisterGrpc(obj GrpcManager) {
	if _, ok := i.grpcObjs[obj.Name()]; ok {
		logger.L().Errorw("Grpc 注册失败",
			"name", obj.Name(),
			"reason", "已经注册过了，无法重复注册",
		)
	} else {
		i.grpcObjs[obj.Name()] = obj
		//logger.L().Infow("Grpc 注册成功",
		//	"name", obj.Name(),
		//)
	}
}

func (i *IocContainter) GetGrpc(name string) GrpcManager {
	if obj, ok := i.grpcObjs[name]; ok {
		return obj
	}
	logger.L().PanicWithIconw("Grpc 未注册",
		"name", name,
		"error", fmt.Errorf("Grpc %s 未注册，故无法获取", name),
	)
	return nil
}

func (i *IocContainter) InitGrpcs(svc *grpc.Server) {
	for _, obj := range i.grpcObjs {
		if err := obj.Init(); err != nil {
			logger.L().Errorw("Grpc 初始化失败",
				"name", obj.Name(),
				"error", err,
			)
		}
		obj.RegisterGrpc(svc)
	}
}

// ------------------------------------配置-----------------------------------------------------

func (i *IocContainter) RegisterConf(obj ConfManager) {
	if _, ok := i.confObjs[obj.Name()]; ok {
		logger.L().Infow("Conf 覆盖注册",
			"name", obj.Name(),
			"reason", "已经注册过了，现在覆盖注册",
		)
	}
	i.confObjs[obj.Name()] = obj
	//logger.L().Infow("Conf 注册成功",
	//	"name", obj.Name(),
	//)

}

func (i *IocContainter) GetConf(name string) ConfManager {
	if obj, ok := i.confObjs[name]; ok {
		return obj
	}
	logger.L().PanicWithIconw("Conf 未注册",
		"name", name,
		"error", fmt.Errorf("Conf %s 未注册，故无法获取", name),
	)
	return nil
}

func (i *IocContainter) InitConfs() {
	if i.ConfigEnv.Enabled {
		// 从环境变量加载
		i.LoadConfigFromEnv()
	} else if i.ConfigFile.Enabled {
		prefix := filepath.Ext(i.LoadConfigRequest.ConfigFile.Path)
		if prefix == ".toml" {
			// 从toml文件加载
			i.LoadConfigFromToml(i.LoadConfigRequest.ConfigFile.Path)
		} else if prefix == ".yaml" || prefix == ".yml" {
			// 从yaml文件加载
			i.LoadConfigFromYaml(i.LoadConfigRequest.ConfigFile.Path)
		} else {
			logger.L().PanicWithIconw("配置文件格式错误",
				"path", i.LoadConfigRequest.ConfigFile.Path,
				"error", fmt.Errorf("ConfigFile.Path 文件格式不正确，目前只支持 .toml 和 .yaml 文件"),
			)
		}
	}
	i.ForceLoad = true
	for _, obj := range i.confObjs {
		if err := obj.Init(); err != nil {
			logger.L().Errorw("Conf初始化失败",
				"name", obj.Name(),
				"error", err,
			)
		}
	}
}

// ------------------------------------展示注册的内容-----------------------------------------------------

func (i *IocContainter) InitedRestfulApi() (apis []string) {
	for api := range i.restfulApiObjs {
		apis = append(apis, api)
	}
	return apis
}
func (i *IocContainter) InitedGinApi() (apis []string) {
	for api := range i.ginApiObjs {
		apis = append(apis, api)
	}
	return apis
}
func (i *IocContainter) InitedApp() (apps []string) {
	for app := range i.appObjs {
		apps = append(apps, app)
	}
	return apps
}
func (i *IocContainter) InitedGrpc() (grpcs []string) {
	for grc := range i.grpcObjs {
		grpcs = append(grpcs, grc)
	}
	return grpcs
}
